#include <REGX52.H>
#include <string.h>
#include "serial.h"
#include "LCD1602.h"
#include "Pin.h"

extern unsigned int rate;
unsigned int* yhl = &rate;

// 串口初始化
void UART_Init(){
	//设置串口为模式1 并打开串口开关
	SCON = 0x50;
	//波特率不翻倍（
	PCON &= 0x7F;
	PCON |= 0x80;
	//定时器1初始化 —— 设置为8位自动重载
	TMOD &= 0x0F;
	TMOD |= 0x20;
	//由波特率为19200计算得到初值如下
	TH1 = 0xFD;
	TL1 = 0xFD;
	// 打开串口中断
	ES = 1;
	//不开启定时器1中断
	ET1 = 0;
	// 开启总中断
	EA = 1;
	//开启定时器1工作开关
	TR1 = 1;
}

// 发送单个字节
void UART_SendByte(unsigned char Byte){
	// 将数据存入SBUF中发送
	SBUF = Byte;
	// 发送后TI置位 下面循环无效（查询方式
	while(!TI);
	// TI重新清零方可再次发送
	TI = 0;
}

// 发送字符串
void UART_SendString(unsigned char *str){
	// 每个字符串都是以'\0'结尾的 当没到字符串末尾时一直发送下一位
	while(*str != '\0'){
		UART_SendByte(*str);
		*str++;
	}
}

// 基本要求：发送接收到的数据
void UART_SendReceive(){
	unsigned char dat;
	// 当收到有数据时 RI置1 while循环失效（查询方式
	while(!RI);
	// 将收到的数据存入dat 变量中
	dat = SBUF;
	// 让RI清零 才能开启下一次查询
	RI = 0;
	// 将数据 dat 发送
	UART_SendByte(dat);	
}

void UART_Judge(){
	// 创建一个数组用以存放接收数据 长度为7 和 "#start"相同即可
	static unsigned char rec_data[9] = "";
	
	// 定义一个辅助变量 i 用以指示当前数组下标
	static unsigned char i = 0;
	
  // 定义一个变量用以查看当前是否可以直接写入接收数组
	static unsigned char rec = 0;
	
	// 定义一个辅助变量udrn来接收SBUF的值
	unsigned char udrn;
	
	// 接收数据
	udrn = SBUF;
	// RI清零 才能再次接收
	RI = 0;
	// 若接收到的数据为'#' 
	if(udrn == '#'){
		// 开始接收
		rec  = 1;
		// 将接收到的数据存入起始位
		i = 0;
		// 每次接收前将接收数组清空
		memset(rec_data,0,sizeof(rec_data));
	}
	
	// 若开始接收则直接存入
	if(rec){
		rec_data[i++] = udrn;
	}
	
	// 若接收满了或接收到结束标志符'*'
	if( i == 9 || udrn == '*'){
		rec = 0;
		// 比较接收到的字符串是否和“#指令*”相同
		
		// low —— 低速
		*yhl = (!strncmp(rec_data,"#low*",5)) ? 1 : (*yhl);
		// medium —— 中速
		*yhl = (!strncmp(rec_data,"#medium*",9)) ? 2 : (*yhl);
		// high —— 高速
		*yhl = (!strncmp(rec_data,"#high*",6)) ? 3 : (*yhl);
		// stop —— 停止
		*yhl = (!strncmp(rec_data,"#stop*",6)) ? 0 : (*yhl);
		// faster —— 加速
		*yhl = ((!strncmp(rec_data,"#faster*",9))&& ((*yhl) < 3)) ? (*yhl)+1 : (*yhl);
		// slower —— 减速
		*yhl = ((!strncmp(rec_data,"#slower*",9))&& ((*yhl) > 0)) ? (*yhl)-1 : (*yhl);
		
		// 调完状态之后显示在LCD上
		LCD_ShowStyle();
		
		}
	}
